#include "wifihotspotcontroller.h"
#include <QDebug>
#include <QFile>
#include <QTextStream>
#include <QCoreApplication>

const QString HOSTAPD_CONF_PATH = "/etc/hostapd/hostapd.conf";
const QString DNSMASQ_CONF_PATH = "/etc/dnsmasq.conf";

WiFiHotspotController::WiFiHotspotController(QObject *parent)
    : QObject(parent), m_process(new QProcess(this)), m_hotspotActive(false)
{
    connect(m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
            this, &WiFiHotspotController::onProcessFinished);
    connect(m_process, &QProcess::errorOccurred, this, &WiFiHotspotController::onProcessErrorOccurred);
    connect(m_process, &QProcess::readyReadStandardOutput, this, &WiFiHotspotController::handleReadyReadStandardOutput);
    connect(m_process, &QProcess::readyReadStandardError, this, &WiFiHotspotController::handleReadyReadStandardError);

    findWirelessInterface();
    connect(qApp, &QCoreApplication::aboutToQuit, this, &WiFiHotspotController::cleanup);
}

WiFiHotspotController::~WiFiHotspotController()
{
    cleanup();
}

void WiFiHotspotController::cleanup()
{
    if (isHotspotActive()) {
        stopHotspot();
    }
}

bool WiFiHotspotController::isHotspotActive() const
{
    return m_hotspotActive;
    }

QString WiFiHotspotController::getWirelessInterface() const
{
    return m_interfaceName;
}

void WiFiHotspotController::findWirelessInterface()
{
    QProcess proc;
    proc.start("iw", QStringList() << "dev");
    proc.waitForFinished();
    QString output = proc.readAllStandardOutput();
    QStringList lines = output.split('\n');
    for (const QString &line : lines) {
        if (line.trimmed().startsWith("Interface")) {
            m_interfaceName = line.trimmed().section(' ', 1, 1);
            emit logMessage(QString("Found wireless interface: %1").arg(m_interfaceName));
            return;
        }
    }
    m_interfaceName = "wlan0"; // Fallback
    emit logMessage(QString("Could not auto-detect wireless interface, falling back to '%1'").arg(m_interfaceName));
}

bool WiFiHotspotController::checkDependencies()
{
    QStringList dependencies = {"hostapd", "dnsmasq", "pgrep", "nmcli", "ip", "iw"};
    bool allFound = true;
    for (const QString &cmd : dependencies) {
        QProcess proc;
        proc.start("which", QStringList() << cmd);
        proc.waitForFinished();
        if (proc.exitCode() != 0) {
            emit logMessage(QString("Dependency missing: %1").arg(cmd));
            allFound = false;
    }
    }
    if (!allFound) {
        emit hotspotStateChanged(false, "Error: Missing required command-line tools.");
    }
    return allFound;
}

void WiFiHotspotController::startHotspot()
{
    if (m_hotspotActive) {
        emit logMessage("Hotspot is already active. Restarting...");
        stopHotspot();
        // It's better to wait for stop to complete, but for a simple restart this might be okay.
        // A more robust solution would use signals/slots to sequence this.
    }
    
    if (!checkDependencies()) return;

    if (m_interfaceName.isEmpty()) {
        emit logMessage("Error: No wireless interface specified.");
        emit hotspotStateChanged(false, "Error: No wireless interface specified.");
        return;
    }
    
    emit logMessage("Starting hotspot...");

    // Release interface from NetworkManager
    startProcess("nmcli", QStringList() << "dev" << "set" << m_interfaceName << "managed" << "no");

    // Clean up previous IP addresses
    startProcess("ip", QStringList() << "addr" << "flush" << "dev" << m_interfaceName);

    // Start hostapd
    startProcess("hostapd", QStringList() << "-B" << HOSTAPD_CONF_PATH);

    // Configure IP address
    startProcess("ip", QStringList() << "addr" << "add" << "192.168.1.1/24" << "dev" << m_interfaceName);

    // Start dnsmasq
    QStringList dnsmasqArgs;
    dnsmasqArgs << QString("--conf-file=%1").arg(DNSMASQ_CONF_PATH) 
                << "--no-resolv"
                << "--except-interface=lo"
                << QString("--interface=%1").arg(m_interfaceName)
                << "--dhcp-range=192.168.1.10,192.168.1.100,255.255.255.0,12h"
                << "--port=0"; // Don't listen on port 53 for DNS
    startProcess("dnsmasq", dnsmasqArgs);


    m_hotspotActive = true;
    emit hotspotStateChanged(true, "Hotspot is now active.");
    emit logMessage(QString("Hotspot started on interface %1.").arg(m_interfaceName));
}


void WiFiHotspotController::stopHotspot()
{
    emit logMessage("Stopping hotspot...");

    // Kill the processes by name
    startProcess("killall", QStringList() << "hostapd");
    startProcess("killall", QStringList() << "dnsmasq");
    
    // Give some time for processes to terminate
    QProcess p;
    p.start("sleep", QStringList() << "1");
    p.waitForFinished();

    // Clean up IP address
    startProcess("ip", QStringList() << "addr" << "flush" << "dev" << m_interfaceName);

    // Return interface to NetworkManager
    startProcess("nmcli", QStringList() << "dev" << "set" << m_interfaceName << "managed" << "yes");


    m_hotspotActive = false;
    emit hotspotStateChanged(false, "Hotspot has been stopped.");
    emit logMessage("Hotspot stopped.");
}


void WiFiHotspotController::startProcess(const QString& program, const QStringList& args)
{
    QProcess *proc = new QProcess(this);
    connect(proc, &QProcess::readyReadStandardOutput, this, &WiFiHotspotController::handleReadyReadStandardOutput);
    connect(proc, &QProcess::readyReadStandardError, this, &WiFiHotspotController::handleReadyReadStandardError);
    
    proc->start(program, args);
    proc->waitForStarted();
    m_managedProcesses.append(proc);
}


void WiFiHotspotController::onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
    Q_UNUSED(exitCode);
    Q_UNUSED(exitStatus);
    // This slot is now less important as we manage multiple processes.
}

void WiFiHotspotController::onProcessErrorOccurred(QProcess::ProcessError error)
{
    if (error == QProcess::FailedToStart) {
        QProcess *p = qobject_cast<QProcess*>(sender());
        emit logMessage(QString("Error starting process: %1").arg(p->program()));
    }
}

void WiFiHotspotController::handleReadyReadStandardOutput()
{
    QProcess *p = qobject_cast<QProcess*>(sender());
    if (p) {
        emit logMessage(QString("[%1] %2").arg(p->program()).arg(QString::fromLocal8Bit(p->readAllStandardOutput())));
    }
}

void WiFiHotspotController::handleReadyReadStandardError()
{
     QProcess *p = qobject_cast<QProcess*>(sender());
    if (p) {
        emit logMessage(QString("[%1_ERROR] %2").arg(p->program()).arg(QString::fromLocal8Bit(p->readAllStandardError())));
    }
} 